// Contient toutes les spécifications de classes nécessaires
// pour représenter l'arbre abstrait
#ifndef ARBRE_H_
#define ARBRE_H_

#include <vector>
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;

#include "Symbole.h"
#include  "Type.h"

////////////////////////////////////////////////////////////////////////////////

class accFichier {
private:
    fstream fichier;
public:
   
    void ouvrirF();
    void fermerF();
    void ecrireF(string code);


};

class Noeud {
    // classe abstraite dont dériveront toutes les classes servant à représenter l'arbre abstrait
    // Remarque : la classe ne contient aucun constructeur
public:
    virtual Type * getValeur() = 0; // méthode pure (non implémentée) qui rend la classe abstraite

    virtual void afficher(unsigned short indentation = 0) {
        cout << setw(4 * indentation) << " ";
    }
    // pour afficher un noeud avec un décalage (indentation) proportionnel à son niveau dans l'arbre

    inline virtual void transcod(accFichier* aF){;}

    virtual ~Noeud() {
    } // présence d'un destructeur virtuel conseillée dans les classes abstraites
};

////////////////////////////////////////////////////////////////////////////////

class NoeudSeqInst : public Noeud {
    // classe pour représenter un noeud "sequence d'instruction"
    // qui a autant de fils que d'instructions dans la séquence
public:
    NoeudSeqInst(); // construit une séquence d'instruction vide

    ~NoeudSeqInst() {
    } // à cause du destructeur virtuel de la classe Noeud
    Type* getValeur(); // évalue chaque instruction de la séquence
    void afficher(unsigned short indentation = 0); // affiche la séquence d'instructions
    void ajouteInstruction(Noeud* instruction); // ajoute une instruction à la séquence

    void transcod(accFichier aF);
private:
    vector<Noeud *> tabInst; // pour stocker les instructions de la séquence
};

////////////////////////////////////////////////////////////////////////////////

class NoeudAffectation : public Noeud {
    // classe pour représenter un noeud "affectation"
    // composé de 2 fils : la variable et l'expression qu'on lui affecte
public:
    NoeudAffectation(Noeud* variable, Noeud* expression); // construit une affectation

    ~NoeudAffectation() {
    } // à cause du destructeur virtuel de la classe Noeud
    Type* getValeur(); // évalue l'expression et affecte sa valeur à la variable
    void afficher(unsigned short indentation = 0); // affiche l'affectation
    void transcod(accFichier aF);
private:
    Noeud* variable;
    Noeud* expression;
};

////////////////////////////////////////////////////////////////////////////////

class NoeudOperateurBinaire : public Noeud {
    // classe pour représenter un noeud "opération arithmétique" composé d'un opérateur (+-*/)
    // et de 2 fils : l'opérande gauche et l'opérande droit
public:
    NoeudOperateurBinaire(Symbole operateur, Noeud* operandeGauche, Noeud* operandeDroit);
    // construit une opération binaire : operandeGauche operateur OperandeDroit

    ~NoeudOperateurBinaire() {
    } // à cause du destructeur virtuel de la classe Noeud
    Type * getValeur(); // évalue l'operande gauche, l'operande droit et applique l'opérateur
    void afficher(unsigned short indentation = 0); // affiche l'opération
    void transcod(accFichier aF);
private:
    Symbole operateur;
    Noeud* operandeGauche;
    Noeud* operandeDroit;
};
////////////////////////////////////////////////////////////////////////////////

class NoeudSi : public Noeud {
    // classe pour représenter un noeud "si" composé d'un opérateur si sinonsi sinon
public:
    NoeudSi();
    // construit une opération binaire : operandeGauche operateur OperandeDroit

    ~NoeudSi() {
    } // à cause du destructeur virtuel de la classe Noeud

    Type* getValeur() {return NULL;
    } // évalue l'operande gauche, l'operande droit et applique l'opérateur
    void afficher(unsigned short indentation = 0); // affiche l'opération
    void addI(Noeud * noeud); // Ajoute l'instruction
    void addC(Noeud * noeud); // Ajoute la condition
    void addS(Noeud * noeud); // Ajoute le "sinon"
    void transcod(accFichier aF);

private:
    vector<Noeud *> v_conditions; // Vecteur de conditions
    vector<Noeud *> v_instrus; // Vecteur d'instructions
    Noeud * inst_sinon; // Vecteur de l'instruction "sinon"
};

////////////////////////////////////////////////////////////////////////////////

class NoeudLire : public Noeud {
    // classe pour représenter un noeud "lire" composé d'un symbole à lire
public:
    NoeudLire(Symbole s);

    ~NoeudLire() {
    } // à cause du destructeur virtuel de la classe Noeud

    Type* getValeur() {return NULL;
    }
    void afficher(unsigned short indentation = 0); // affiche le "lire"
    void transcod(accFichier aF);
private:
    Symbole symb; // Le symbole à lire
};

////////////////////////////////////////////////////////////////////////////////

class NoeudBoucle : public Noeud {
    // classe pour représenter un noeud "boucle" composé d'une condition d'itération
    // et d'une séquence d'instructions
public:
    NoeudBoucle(Noeud * noeudC, Noeud * noeudS);
    // construit une boucle avec un noeud condition et un noeud instruction

    ~NoeudBoucle() {
    } // à cause du destructeur virtuel de la classe Noeud

    Type* getValeur() { return NULL;
    } // évalue l'operande gauche, l'operande droit et applique l'opérateur
    void addC(Noeud * noeud); // Ajoute la condition
    void addS(Noeud * noeud); // Ajoute la séquence d'instruction
    void afficher(unsigned short indentation = 0); // affiche la boucle
    void transcod(accFichier aF);

protected:
    Noeud* condition;
    Noeud* seqinstr;
};

////////////////////////////////////////////////////////////////////////////////

class NoeudRepeterJsqa : public NoeudBoucle {
    // classe pour représenter un répéter jusqu'à (do while)
public:
    NoeudRepeterJsqa(Noeud * condi, Noeud * seqinst, Noeud * seqinst2);
    // construit une boucle avec un noeud condition et un noeud instruction

    ~NoeudRepeterJsqa() {
    } // à cause du destructeur virtuel de la classe Noeud
    void afficher(unsigned short indentation = 0); // affiche l'opération
    void addS2(Noeud * seqinst2); // Ajoute la séquence d'instruction
    void transcod(accFichier aF);
private:
    Noeud* seqinstr2;
};

////////////////////////////////////////////////////////////////////////////////

class NoeudPour : public NoeudBoucle {
    // classe pour représenter un noeud "pour" composé de deux affectations et
    // d'une séquence d'instruction
public:
    NoeudPour(Noeud * affect1, Noeud * expBool, Noeud * affect2, Noeud * seqinst);
    // construit un noeud Pour avec une affectation: int i=0;
    // une expression booléene : i<5;
    // une affectation : i++;
    // et une seq d'instruction

    ~NoeudPour() {
    } // à cause du destructeur virtuel de la classe Noeud
    void afficher(unsigned short indentation = 0); // affiche l'opération
    void addA1(Noeud * affect1); // Ajouter la première affectation
    void addA2(Noeud * affect2); // Ajouter la deuxième affectation
    void transcod(accFichier aF);
private:
    Noeud* affectation1;
    Noeud* affectation2;
};

////////////////////////////////////////////////////////////////////////////////

class NoeudEcrire : public Noeud {
    // classe pour représenter un noeud "ecrire" composé d'un symbole à ecrire
public:
    NoeudEcrire(Noeud * noeud);

    ~NoeudEcrire() {
    } // à cause du destructeur virtuel de la classe Noeud

    Type* getValeur() { return NULL;
    }
    void afficher(unsigned short indentation = 0); // affiche l'écrire
    void transcod(accFichier aF){;}

private:
    Noeud * argument; // Le symbole à écrire
};

////////////////////////////////////////////////////////////////////////////////

class NoeudChaine : public Noeud {
    // classe pour représenter un noeud chaine
public:
    NoeudChaine(Symbole s);
    // construit une chaine à partir d'un symbole

    ~NoeudChaine() {
    } // à cause du destructeur virtuel de la classe Noeud

    Type* getValeur() { return NULL;
    }
    void afficher(unsigned short indentation = 0); // affiche l'opération
    void transcod(accFichier aF);

private:
    Symbole symb;
};

#endif /* ARBRE_H_ */
